package cn.iocoder.lw.module.core.service.workorder;

import cn.iocoder.lw.framework.common.pojo.PageResult;
import cn.iocoder.lw.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.lw.module.core.controller.admin.workorder.vo.report.WorkOrderReportGenerateReqVO;
import cn.iocoder.lw.module.core.controller.admin.workorder.vo.report.WorkOrderReportPageReqVO;
import cn.iocoder.lw.module.core.controller.admin.workorder.vo.report.WorkOrderStatisticsRespVO;
import cn.iocoder.lw.module.core.controller.admin.workorder.vo.report.WorkOrderOverallStatisticsRespVO;
import cn.iocoder.lw.module.core.dal.dataobject.workorder.CoreWorkOrderDO;
import cn.iocoder.lw.module.core.dal.mysql.workorder.CoreWorkOrderMapper;
import cn.iocoder.lw.module.core.enums.workorder.WorkOrderStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 工单报表 Service 实现类
 *
 * 注意：由于避免跨模块依赖，本实现使用简化的方式处理用户信息
 */
@Service
@Slf4j
public class WorkOrderReportServiceImpl implements WorkOrderReportService {

    @Resource
    private CoreWorkOrderMapper workOrderMapper;

    @Override
    public List<WorkOrderStatisticsRespVO> generateWorkOrderReport(WorkOrderReportGenerateReqVO generateReqVO) {
        log.info("[generateWorkOrderReport][开始生成工单报表，reportType={}, startTime={}, endTime={}, userType={}]",
                generateReqVO.getReportType(), generateReqVO.getStartTime(), generateReqVO.getEndTime(), generateReqVO.getUserType());

        // 构建工单查询条件
        LambdaQueryWrapperX<CoreWorkOrderDO> wrapper = new LambdaQueryWrapperX<>();
        wrapper.betweenIfPresent(CoreWorkOrderDO::getCreateTime, generateReqVO.getStartTime(), generateReqVO.getEndTime());

        List<CoreWorkOrderDO> workOrders = workOrderMapper.selectList(wrapper);

        // 根据报表类型进行分组统计
        List<WorkOrderStatisticsRespVO> reportList = new ArrayList<>();

        if (generateReqVO.getReportType() == 1) {
            // 发起人统计 - 按发起人ID分组
            Map<Long, List<CoreWorkOrderDO>> initiatorGroups = workOrders.stream()
                    .filter(order -> order.getInitiatorId() != null)
                    .collect(Collectors.groupingBy(CoreWorkOrderDO::getInitiatorId));

            for (Map.Entry<Long, List<CoreWorkOrderDO>> entry : initiatorGroups.entrySet()) {
                Long initiatorId = entry.getKey();
                List<CoreWorkOrderDO> userWorkOrders = entry.getValue();

                WorkOrderStatisticsRespVO statistics = buildStatisticsFromWorkOrders(
                    userWorkOrders, initiatorId, generateReqVO, 1, "发起人" + initiatorId);
                if (statistics.getTotalWorkOrderCount() > 0) {
                    reportList.add(statistics);
                }
            }
        } else if (generateReqVO.getReportType() == 2) {
            // 接单人统计 - 按接单人ID分组
            Map<Long, List<CoreWorkOrderDO>> assigneeGroups = workOrders.stream()
                    .filter(order -> order.getAssigneeId() != null)
                    .collect(Collectors.groupingBy(CoreWorkOrderDO::getAssigneeId));

            for (Map.Entry<Long, List<CoreWorkOrderDO>> entry : assigneeGroups.entrySet()) {
                Long assigneeId = entry.getKey();
                List<CoreWorkOrderDO> userWorkOrders = entry.getValue();

                WorkOrderStatisticsRespVO statistics = buildStatisticsFromWorkOrders(
                    userWorkOrders, assigneeId, generateReqVO, 0, "接单人" + assigneeId);
                if (statistics.getTotalWorkOrderCount() > 0) {
                    reportList.add(statistics);
                }
            }
        }

        log.info("[generateWorkOrderReport][工单报表生成完成，共生成{}条记录]", reportList.size());
        return reportList;
    }

    @Override
    public PageResult<WorkOrderStatisticsRespVO> getWorkOrderReportPage(WorkOrderReportPageReqVO pageReqVO) {
        log.info("[getWorkOrderReportPage][获取工单报表分页，pageReqVO={}]", pageReqVO);

        // 转换为生成请求并查询数据
        WorkOrderReportGenerateReqVO generateReqVO = new WorkOrderReportGenerateReqVO();
        generateReqVO.setReportType(pageReqVO.getReportType());
        generateReqVO.setUserType(pageReqVO.getUserType());
        generateReqVO.setStartTime(pageReqVO.getStatisticsStartTime());
        generateReqVO.setEndTime(pageReqVO.getStatisticsEndTime());

        List<WorkOrderStatisticsRespVO> allData = generateWorkOrderReport(generateReqVO);

        // 过滤条件
        if (pageReqVO.getUserId() != null) {
            allData = allData.stream()
                    .filter(item -> item.getUserId().equals(pageReqVO.getUserId()))
                    .collect(Collectors.toList());
        }

        // 手动分页
        int total = allData.size();
        int pageSize = pageReqVO.getPageSize();
        int pageNum = pageReqVO.getPageNo();
        int start = (pageNum - 1) * pageSize;
        int end = Math.min(start + pageSize, total);

        List<WorkOrderStatisticsRespVO> pageData = start < total ? allData.subList(start, end) : new ArrayList<>();

        return new PageResult<>(pageData, (long) total);
    }

    @Override
    public WorkOrderStatisticsRespVO getUserWorkOrderReport(Long userId, Integer reportType, Integer userType,
                                                           LocalDateTime startTime, LocalDateTime endTime) {
        log.info("[getUserWorkOrderReport][获取用户工单统计，userId={}, reportType={}, userType={}]",
                userId, reportType, userType);

        // 构建工单查询条件
        LambdaQueryWrapperX<CoreWorkOrderDO> wrapper = new LambdaQueryWrapperX<>();
        wrapper.betweenIfPresent(CoreWorkOrderDO::getCreateTime, startTime, endTime);

        if (reportType == 1) {
            // 发起人统计
            wrapper.eq(CoreWorkOrderDO::getInitiatorId, userId);
        } else if (reportType == 2) {
            // 接单人统计
            wrapper.eq(CoreWorkOrderDO::getAssigneeId, userId);
        }

        List<CoreWorkOrderDO> workOrders = workOrderMapper.selectList(wrapper);

        if (workOrders.isEmpty()) {
            return WorkOrderStatisticsRespVO.builder()
                    .userId(userId)
                    .userName(reportType == 1 ? "发起人" + userId : "接单人" + userId)
                    .userMobile("")
                    .userType(userType != null ? userType : (reportType == 1 ? 1 : 0))
                    .totalWorkOrderCount(0)
                    .completedWorkOrderCount(0)
                    .inProgressWorkOrderCount(0)
                    .pendingWorkOrderCount(0)
                    .cancelledWorkOrderCount(0)
                    .totalAmount(BigDecimal.ZERO)
                    .averageAmount(BigDecimal.ZERO)
                    .completionRate(BigDecimal.ZERO)
                    .averageProcessHours(BigDecimal.ZERO)
                    .statisticsStartTime(startTime)
                    .statisticsEndTime(endTime)
                    .workOrderDetails(new ArrayList<>())
                    .build();
        }

        return buildStatisticsFromWorkOrders(workOrders, userId, null,
                userType != null ? userType : (reportType == 1 ? 1 : 0),
                reportType == 1 ? "发起人" + userId : "接单人" + userId);
    }

    @Override
    public WorkOrderOverallStatisticsRespVO getOverallStatistics(LocalDateTime startTime, LocalDateTime endTime) {
        log.info("[getOverallStatistics][获取工单总体统计，startTime={}, endTime={}]", startTime, endTime);

        // 构建查询条件
        LambdaQueryWrapperX<CoreWorkOrderDO> wrapper = new LambdaQueryWrapperX<>();
        wrapper.betweenIfPresent(CoreWorkOrderDO::getCreateTime, startTime, endTime);

        List<CoreWorkOrderDO> workOrders = workOrderMapper.selectList(wrapper);

        if (workOrders.isEmpty()) {
            return WorkOrderOverallStatisticsRespVO.builder()
                    .totalWorkOrderCount(0L)
                    .completedWorkOrderCount(0L)
                    .inProgressWorkOrderCount(0L)
                    .pendingWorkOrderCount(0L)
                    .cancelledWorkOrderCount(0L)
                    .totalAmount(BigDecimal.ZERO)
                    .averageAmount(BigDecimal.ZERO)
                    .completionRate(BigDecimal.ZERO)
                    .averageProcessHours(BigDecimal.ZERO)
                    .build();
        }

        // 按状态分组统计
        Map<Integer, List<CoreWorkOrderDO>> statusGroups = workOrders.stream()
                .collect(Collectors.groupingBy(CoreWorkOrderDO::getStatus));

        long totalCount = workOrders.size();
        long completedCount = statusGroups.getOrDefault(WorkOrderStatusEnum.COMPLETED.getStatus(), new ArrayList<>()).size();
        long inProgressCount = statusGroups.getOrDefault(WorkOrderStatusEnum.IN_PROGRESS.getStatus(), new ArrayList<>()).size();
        long pendingCount = statusGroups.getOrDefault(WorkOrderStatusEnum.PENDING_ASSIGN.getStatus(), new ArrayList<>()).size();
        long cancelledCount = statusGroups.getOrDefault(WorkOrderStatusEnum.CANCELLED.getStatus(), new ArrayList<>()).size();

        BigDecimal totalAmount = workOrders.stream()
                .filter(order -> order.getTotalCost() != null)
                .map(CoreWorkOrderDO::getTotalCost)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal averageAmount = totalCount > 0 ?
                totalAmount.divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP) : BigDecimal.ZERO;

        BigDecimal completionRate = totalCount > 0 ?
                BigDecimal.valueOf(completedCount)
                        .multiply(BigDecimal.valueOf(100))
                        .divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP) :
                BigDecimal.ZERO;

        // 计算平均处理时长（需要单独查询已完成的工单）
        List<CoreWorkOrderDO> completedOrders = statusGroups.getOrDefault(WorkOrderStatusEnum.COMPLETED.getStatus(), new ArrayList<>());
        BigDecimal averageProcessHours = BigDecimal.ZERO;
        if (!completedOrders.isEmpty()) {
            double totalHours = completedOrders.stream()
                    .mapToDouble(order -> {
                        if (order.getUpdateTime() != null && order.getCreateTime() != null) {
                            return Duration.between(order.getCreateTime(), order.getUpdateTime()).toHours();
                        }
                        return 0;
                    })
                    .sum();
            averageProcessHours = BigDecimal.valueOf(totalHours / completedOrders.size()).setScale(2, RoundingMode.HALF_UP);
        }

        return WorkOrderOverallStatisticsRespVO.builder()
                .totalWorkOrderCount(totalCount)
                .completedWorkOrderCount(completedCount)
                .inProgressWorkOrderCount(inProgressCount)
                .pendingWorkOrderCount(pendingCount)
                .cancelledWorkOrderCount(cancelledCount)
                .totalAmount(totalAmount)
                .averageAmount(averageAmount)
                .completionRate(completionRate)
                .averageProcessHours(averageProcessHours)
                .build();
    }

    /**
     * 根据工单列表构建统计VO对象
     */
    private WorkOrderStatisticsRespVO buildStatisticsFromWorkOrders(List<CoreWorkOrderDO> workOrders, Long userId,
                                                               WorkOrderReportGenerateReqVO generateReqVO,
                                                               Integer userType, String userName) {
        if (workOrders.isEmpty()) {
            return WorkOrderStatisticsRespVO.builder()
                    .userId(userId)
                    .userName(userName)
                    .userMobile("")
                    .userType(userType)
                    .totalWorkOrderCount(0)
                    .completedWorkOrderCount(0)
                    .inProgressWorkOrderCount(0)
                    .pendingWorkOrderCount(0)
                    .cancelledWorkOrderCount(0)
                    .totalAmount(BigDecimal.ZERO)
                    .averageAmount(BigDecimal.ZERO)
                    .completionRate(BigDecimal.ZERO)
                    .averageProcessHours(BigDecimal.ZERO)
                    .statisticsStartTime(generateReqVO != null ? generateReqVO.getStartTime() : null)
                    .statisticsEndTime(generateReqVO != null ? generateReqVO.getEndTime() : null)
                    .workOrderDetails(new ArrayList<>())
                    .build();
        }

        // 按状态分组统计
        Map<Integer, List<CoreWorkOrderDO>> statusGroups = workOrders.stream()
                .collect(Collectors.groupingBy(CoreWorkOrderDO::getStatus));

        int totalCount = workOrders.size();
        int completedCount = statusGroups.getOrDefault(WorkOrderStatusEnum.COMPLETED.getStatus(), new ArrayList<>()).size();
        int inProgressCount = statusGroups.getOrDefault(WorkOrderStatusEnum.IN_PROGRESS.getStatus(), new ArrayList<>()).size();
        int pendingCount = statusGroups.getOrDefault(WorkOrderStatusEnum.PENDING_ASSIGN.getStatus(), new ArrayList<>()).size();
        int cancelledCount = statusGroups.getOrDefault(WorkOrderStatusEnum.CANCELLED.getStatus(), new ArrayList<>()).size();

        BigDecimal totalAmount = workOrders.stream()
                .filter(order -> order.getTotalCost() != null)
                .map(CoreWorkOrderDO::getTotalCost)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal averageAmount = totalCount > 0 ?
                totalAmount.divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP) : BigDecimal.ZERO;

        BigDecimal completionRate = totalCount > 0 ?
                BigDecimal.valueOf(completedCount)
                        .multiply(BigDecimal.valueOf(100))
                        .divide(BigDecimal.valueOf(totalCount), 2, RoundingMode.HALF_UP) :
                BigDecimal.ZERO;

        // 计算平均处理时长（仅已完成工单）
        List<CoreWorkOrderDO> completedOrders = statusGroups.getOrDefault(WorkOrderStatusEnum.COMPLETED.getStatus(), new ArrayList<>());
        BigDecimal averageProcessHours = BigDecimal.ZERO;
        if (!completedOrders.isEmpty()) {
            double totalHours = completedOrders.stream()
                    .mapToDouble(order -> {
                        if (order.getUpdateTime() != null && order.getCreateTime() != null) {
                            return Duration.between(order.getCreateTime(), order.getUpdateTime()).toHours();
                        }
                        return 0;
                    })
                    .sum();
            averageProcessHours = BigDecimal.valueOf(totalHours / completedOrders.size()).setScale(2, RoundingMode.HALF_UP);
        }

        // 工单详情列表
        List<WorkOrderStatisticsRespVO.WorkOrderDetailRespVO> workOrderDetails = workOrders.stream()
                .map(this::convertToDetailVO)
                .collect(Collectors.toList());

        return WorkOrderStatisticsRespVO.builder()
                .userId(userId)
                .userName(userName)
                .userMobile("") // 简化实现，不查询手机号
                .userType(userType)
                .totalWorkOrderCount(totalCount)
                .completedWorkOrderCount(completedCount)
                .inProgressWorkOrderCount(inProgressCount)
                .pendingWorkOrderCount(pendingCount)
                .cancelledWorkOrderCount(cancelledCount)
                .totalAmount(totalAmount)
                .averageAmount(averageAmount)
                .completionRate(completionRate)
                .averageProcessHours(averageProcessHours)
                .statisticsStartTime(generateReqVO != null ? generateReqVO.getStartTime() : null)
                .statisticsEndTime(generateReqVO != null ? generateReqVO.getEndTime() : null)
                .workOrderDetails(workOrderDetails)
                .build();
    }

    /**
     * 转换为工单详情VO
     */
    private WorkOrderStatisticsRespVO.WorkOrderDetailRespVO convertToDetailVO(CoreWorkOrderDO workOrder) {
        return WorkOrderStatisticsRespVO.WorkOrderDetailRespVO.builder()
                .id(workOrder.getId())
                .orderNo(workOrder.getOrderNo())
                .projectId(workOrder.getProjectId())
                .houseId(workOrder.getHouseId())
                .deviceId(workOrder.getDeviceId())
                .problemDescription(workOrder.getProblemDescription())
                .doorToDoorTime(workOrder.getDoorToDoorTime())
                .status(workOrder.getStatus())
                .totalCost(workOrder.getTotalCost())
                .createTime(workOrder.getCreateTime())
                .updateTime(workOrder.getUpdateTime())
                .build();
    }

}